package org.goldenport.g3.adapters

import org.goldenport.util.QSymbol
import org.goldenport.g3._
import org.goldenport.g3.messages._
import org.goldenport.g3.messages.event._
import org.goldenport.g3.events._
import org.goldenport.g3.events.event._
import org.goldenport.application.GApplicationDescriptor
import org.goldenport.Goldenport
import org.goldenport.exporter.FirstLeafOrZipResultExporterClass

/**
 * @since   Nov. 28, 2011
 * @version Dec.  5, 2011
 * @author  ASAMI, Tomoharu
 */
class GoldenportAdapter(val driver: GoldenportDriver) extends G3Adapter {
  override def open_Adapter() {
    driver.open(context)
  }

  override def close_Adapter() {
    driver.close()
  }

  override protected def do_Action(content: AnyRef, parcel: G3Parcel, ctx: G3AgentContext): AnyRef = {
    content match {
      case cmd: G3Command => driver.execute(cmd, ctx)
    }
  }
}

object GoldenportAdapter {
  def create(desc: GApplicationDescriptor): GoldenportAdapter = {
    new GoldenportAdapter(GoldenportDriver.create(desc))
  }

  def create(gp: Goldenport): GoldenportAdapter = {
    new GoldenportAdapter(GoldenportDriver.create(gp))
  }
}

class GoldenportDriver(val goldenport: Goldenport) extends G3Driver {
  protected override def open_Driver(params: List[AnyRef]) {
    goldenport.addExporterClass(FirstLeafOrZipResultExporterClass)
    goldenport.open()
  }

  protected override def close_Driver() {
    goldenport.close()
  }

  protected override def new_Agent(cmd: G3Command, ctx: G3AgentContext): GoldenportDriverAgent = new GoldenportDriverAgent(cmd.uri, goldenport, ctx)
}

object GoldenportDriver {
  def create(desc: GApplicationDescriptor): GoldenportDriver = {
    val gp = new Goldenport(Array(), desc)
    create(gp)
  }

  def create(gp: Goldenport): GoldenportDriver = {
    new GoldenportDriver(gp)
  }
}

class GoldenportDriverAgent(uri: String, val goldenport: Goldenport, context: G3AgentContext) extends G3DriverAgent(uri, context) with UseRecord {
  def get(get: Get): G3Event = {
    val (service, args, params) = _as_operation(get)
    val result = goldenport.executeAsAnyRef(service, args, params)
    new Getted(uri, result)
  }

  def put(put: Put): G3Event = {
    val (service, args, params) = _as_operation(put)
    val result: Option[AnyRef] = goldenport.executeAsAnyRef(service, args, params)
    new Getted(uri, result)
  }

  def post(post: Post): G3Event = {
    val (service, args, params) = _as_operation(post)
    val result = goldenport.executeAsAnyRef(service, args, params)
    new Getted(uri, result)
  }

  def delete(delete: Delete): G3Event = {
    val (service, args, params) = _as_operation(delete)
    val result = goldenport.executeAsAnyRef(service, args, params)
    new Getted(uri, result)
  }

  def mkcol(mkcol: Mkcol): G3Event = {
    val (service, args, params) = _as_operation(mkcol)
    val result = goldenport.executeAsAnyRef(service, args, params)
    new Getted(uri, result)
  }

  private def _as_operation(cmd: RestCommand) = {
    val (service, args, params) = cmd.asOperation
    val normalizedargs = for (a <- args) yield {
      a match {
        case i: FileAttachment => goldenport.createDataSource(i.name, i.get)
        case _ => a
      }
    }
    (service, normalizedargs, params)
  }
}
